package com.ebupt.migu.music.schedule;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.ebupt.migu.music.common.constants.UserGroupConstants;
import com.ebupt.migu.music.common.util.CSVUtils;
import com.ebupt.migu.music.common.util.SqlFormatterUtils;
import com.ebupt.migu.music.redis.service.RedisService;
import com.ebupt.migu.music.userGroup.mapper.CrowdMapper;
import com.google.common.base.Charsets;
import com.google.gson.Gson;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author liuzz
 */
@Slf4j
// @Component
// @EnableScheduling
// @Async
public class UserGroupTask {

    @Value("${spring.elasticsearch.hosts}")
    private String hosts;
    @Value("${spring.elasticsearch.port}")
    private String port;
    @Value("${spring.elasticsearch.alias}")
    private String alias;

    @Autowired
    private CrowdMapper crowdMapper;
    @Autowired
    private RedisService redisService;
    @Autowired
    Configuration configuration; //freeMarker configuration

    static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(8);

    /**
     * @Scheduled(cron = "0/5 * * * * ?")
     * 静态标签创建人群
     */
//    @Scheduled(cron = "${cron.staticLabelGroup}")
    public void staticLabelGroup() {
        log.info("++++++++++++++++++++++++ staticLabelGroup");
        List<HashMap<String, Object>> crowdList = crowdMapper.queryStaticLabelGroup(null);
        Map<String, Object> params = new HashMap<>();

        for (Map<String, Object> crowd : crowdList) {

            String groupId = crowd.get("groupId").toString();
            String groupAttribute = crowd.get("groupAttribute").toString();
            String autoUpdate = crowd.get("autoUpdate").toString();
            log.info("group_id=" + crowd.get("groupId").toString());

            // 先清除redis的数据
            redisService.removePattern(groupId);
            redisService.removePattern(groupId + "-uid");
            redisService.removePattern(groupId + "-imei");
            redisService.removePattern(groupId + "-phone");

            // 状态改为正在更新
            params.clear();
            params.put("createStatus", UserGroupConstants.UPDATING);
            params.put("groupId", groupId);
            crowdMapper.updateCrowd(params);

            // 存入redis
            try {
                Map<String, Integer> retMap = setStaticGroupToRedis(crowd.get("groupId").toString(), hosts, port, alias, groupAttribute, redisService);

                Integer total = retMap.get("total");

                if (total < 7000000) {
                    params.put("createStatus", UserGroupConstants.COMPLETED);
                    params.put("clientUser", retMap.get("clientUser"));
                    params.put("mobileUser", retMap.get("mobileUser"));
                } else {
                    params.put("createStatus", UserGroupConstants.UPDATE_FAILED);
                    if ("0".equals(autoUpdate)) {
                        params.put("remark", "手动更新人群超过700万");
                    } else {
                        params.put("remark", "自动更新人群超过700万");
                    }
                }
                params.put("userGroupSize", total);
            } catch (Exception e) {
                params.put("createStatus", UserGroupConstants.UPDATE_FAILED);
                if ("0".equals(autoUpdate)) {
                    params.put("remark", "手动更新人群失败");
                } else {
                    params.put("remark", "自动更新人群失败");
                }
                e.printStackTrace();
            } finally {
                crowdMapper.updateCrowd(params);
            }
        }
    }

    /**
     * @Scheduled(cron = "0/5 * * * * ?")
     * 文件创建人群
     */
//    @Scheduled(cron = "${cron.fileGroup}")
    public void fileGroup() {
        log.info("++++++++++++++++++++++++ fileGroup");
        List<HashMap<String, Object>> crowdList = crowdMapper.queryFileGroup(null);
        Map<String, Object> params = new HashMap<>();

        for (Map<String, Object> crowd : crowdList) {

            String groupId = crowd.get("groupId").toString();
            String fileImporTtype = crowd.get("fileImportType").toString();
            String fileRename = crowd.get("fileRename").toString();
            String onlySms = crowd.get("onlySms").toString();
            log.info("groupId=" + groupId);
            log.info("file_rename=" + fileRename);
            log.info("file_import_type=" + fileImporTtype);

            // 先清除redis的数据
            redisService.removePattern(groupId);
            redisService.removePattern(groupId + "-uid");
            redisService.removePattern(groupId + "-imei");
            redisService.removePattern(groupId + "-phone");

            // 状态改为正在更新
            params.clear();
            params.put("createStatus", UserGroupConstants.UPDATING);
            params.put("groupId", groupId);
            crowdMapper.updateCrowd(params);

            String[] fileArr = fileRename.split(",");

            try {
                Map<String, Integer> retMap = new HashMap<>();
                retMap.put("inverCnt", 0);
                retMap.put("userGroupSize", 0);
                retMap.put("clientUser", 0);
                retMap.put("mobileUser", 0);

                for (String fileName : fileArr) {

                    log.info("fileName=" + fileName);
                    // 存入redis
                    Map<String, Integer> tmpMap = setFileGroupToRedis(groupId, fileName, fileImporTtype, onlySms, redisService, hosts, port, alias);

                    Integer inverCnt = tmpMap.get("inverCnt") + retMap.get("inverCnt");
                    Integer userGroupSize = tmpMap.get("userGroupSize") + retMap.get("userGroupSize");
                    Integer clientUser = tmpMap.get("clientUser") + retMap.get("clientUser");
                    Integer mobileUser = tmpMap.get("mobileUser") + retMap.get("mobileUser");

                    retMap.put("inverCnt", inverCnt);
                    retMap.put("userGroupSize", userGroupSize);
                    retMap.put("clientUser", clientUser);
                    retMap.put("mobileUser", mobileUser);
                }
                Float inverPercent = Float.valueOf(retMap.get("inverCnt")) / Float.valueOf(retMap.get("userGroupSize")) * 100;
                log.info("===================>>>>>>>>>>>>>>>> inverCnt=" + retMap.get("inverCnt"));
                log.info("===================>>>>>>>>>>>>>>>> userGroupSize=" + retMap.get("userGroupSize"));
                log.info("===================>>>>>>>>>>>>>>>> inverPercent=" + inverPercent);

                // 更新状态
                params.put("createStatus", UserGroupConstants.COMPLETED);
                params.put("groupId", crowd.get("groupId").toString());
                params.put("userGroupSize", retMap.get("userGroupSize"));
                params.put("clientUser", retMap.get("clientUser"));
                params.put("mobileUser", retMap.get("mobileUser"));
                params.put("inverPercent", String.format("%.2f", inverPercent));
            } catch (Exception e) {
                params.put("createStatus", UserGroupConstants.IMPORT_FAILED);
                params.put("remark", "导入人群失败");
                e.printStackTrace();
            } finally {
                crowdMapper.updateCrowd(params);
            }
        }
    }

    /**
     * @Scheduled(cron = "0/5 * * * * ?")
     * 人群重组
     */
//    @Scheduled(cron = "${cron.mergeGroup}")
    public void mergeGroup() {
        log.info("++++++++++++++++++++++++ mergeGroup");

        List<HashMap<String, Object>> crowdList = crowdMapper.queryMergeGroup(null);
        Map<String, Object> params = new HashMap<>();

        for (Map<String, Object> crowd : crowdList) {

            String groupId = crowd.get("groupId").toString();
            String resGroups = crowd.get("resGroups").toString();
            log.info("groupId=" + groupId);
            log.info("res_groups=" + resGroups);

            // 先清除redis的数据
            redisService.removePattern(groupId);
            redisService.removePattern(groupId + "-uid");
            redisService.removePattern(groupId + "-imei");
            redisService.removePattern(groupId + "-phone");

            // 状态改为正在更新
            params.clear();
            params.put("createStatus", UserGroupConstants.UPDATING);
            params.put("groupId", groupId);
            crowdMapper.updateCrowd(params);

            String[] idArr = resGroups.split(",");

            Map<String, Object> crowdForMerge1 = crowdMapper.queryByGroupID(idArr[0]);
            Map<String, Object> crowdForMerge2 = crowdMapper.queryByGroupID(idArr[1]);

            String groupId1 = crowdForMerge1.get("groupId").toString();
            String groupId2 = crowdForMerge2.get("groupId").toString();
            String mergeType = crowd.get("createWay").toString();

            try {
                // 存入redis
                Map<String, Integer> retMap = setMergeGroupToRedis(groupId1, groupId2, groupId, mergeType, redisService, hosts, port, alias);

                // 修改状态
                if (retMap.get("userGroupSize") < 7000000) {
                    params.put("createStatus", UserGroupConstants.COMPLETED);
                } else {
                    params.put("createStatus", UserGroupConstants.UPDATE_FAILED);
                    params.put("remark", "重组人群超过700万");
                }

                params.put("groupId", groupId);
                params.put("userGroupSize", retMap.get("userGroupSize"));
                params.put("clientUser", retMap.get("clientUser"));
                params.put("mobileUser", retMap.get("mobileUser"));
            } catch (Exception e) {
                params.put("createStatus", UserGroupConstants.UPDATE_FAILED);
                params.put("remark", "重组人群失败");
                e.printStackTrace();
            } finally {
                crowdMapper.updateCrowd(params);
            }
        }
    }

    public static String getSqlFromJson(String json, Template template) throws IOException, TemplateException {
        Gson gson = new Gson();
        // 获取用户群属性
        Map<String, Object> map = gson.fromJson(json, Map.class);

        if (map.get("dateType") != null && !"".equals(map.get("dateType").toString()) &&
                map.get("dayCont") != null && !"".equals(map.get("dayCont").toString())) {
            log.info("~~~~~~~~~~dateType=" + map.get("dateType").toString());
            log.info("~~~~~~~~~~dayCont=" + map.get("dayCont").toString());

            Integer dateType = Integer.parseInt(map.get("dateType").toString());
            Integer dayCont = Integer.parseInt(map.get("dayCont").toString());

            if (dateType == 1 || dateType == 3) {
                dayCont = dayCont + 1;
                map.put("dayCont", dayCont);
            }

            log.info("~~~~~~~~~~dayCont=" + map.get("dayCont").toString());
        }

        String sql = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);

        return new SqlFormatterUtils().format(sql);
    }

    public static Map<String, Integer> setStaticGroupToRedis(String groupId, String hosts, String port, String index, String json, RedisService redisService) {
        // 解析json
        Gson gson = new Gson();
        Map<String, Object> groupAttributeMap = gson.fromJson(json, Map.class);

        // 组装查询条件
        List<String> comTypeList = null;
        List<String> ageList = null;
        List<String> areaNameList = null;
        List<String> userLevelList = null;
        List<String> chnIdList = null;
        List<String> phoneSystemList = null;

        String sex = "";
        String loginStatus = "";

        if (groupAttributeMap.get("comType") != null && !"".equals(groupAttributeMap.get("comType").toString())) {
            comTypeList = (List) groupAttributeMap.get("comType");
        }

        if (groupAttributeMap.get("age") != null && !"".equals(groupAttributeMap.get("age").toString())) {
            ageList = (List) groupAttributeMap.get("age");
        }

        if (groupAttributeMap.get("areaName") != null && !"".equals(groupAttributeMap.get("areaName").toString())) {
            areaNameList = (List) groupAttributeMap.get("areaName");
        }

        if (groupAttributeMap.get("userLevel") != null && !"".equals(groupAttributeMap.get("userLevel").toString())) {
            userLevelList = (List) groupAttributeMap.get("userLevel");
        }

        if (groupAttributeMap.get("chnId") != null && !"".equals(groupAttributeMap.get("chnId").toString())) {
            chnIdList = (List) groupAttributeMap.get("chnId");
        }

        if (groupAttributeMap.get("phoneSystem") != null && !"".equals(groupAttributeMap.get("phoneSystem").toString())) {
            phoneSystemList = (List) groupAttributeMap.get("phoneSystem");

            for (int i = 0; i < phoneSystemList.size(); i++) {
                if (phoneSystemList.get(i).equals("1")) {
                    phoneSystemList.set(i, "android");
                } else if (phoneSystemList.get(i).equals("1")) {
                    phoneSystemList.set(i, "ios");
                }
            }
        }

        if (groupAttributeMap.get("sex") != null && !"".equals(groupAttributeMap.get("sex").toString())) {
            sex = groupAttributeMap.get("sex").toString();
        }

        if (groupAttributeMap.get("loginStatus") != null && !"".equals(groupAttributeMap.get("loginStatus").toString())) {
            loginStatus = groupAttributeMap.get("loginStatus").toString();
        }

        String params = "";
        if (
                !((sex == null || "".equals(sex)) &&
                        (loginStatus == null || "".equals(loginStatus)) &&
                        (comTypeList == null || comTypeList.size() == 0) &&
                        (ageList == null || ageList.size() == 0) &&
                        (areaNameList == null || areaNameList.size() == 0) &&
                        (userLevelList == null || userLevelList.size() == 0) &&
                        (chnIdList == null || chnIdList.size() == 0) &&
                        (phoneSystemList == null || phoneSystemList.size() == 0))
        ) {
            sex = String.format("sex:(%s)", "%22" + groupAttributeMap.get("sex").toString() + "%22"); // "双引号转义 %22
            loginStatus = String.format("login_status:(%s)", "%22" + groupAttributeMap.get("loginStatus").toString() + "%22"); // "双引号转义 %22

            String comType = String.format("com_type:(%s)", getParams(comTypeList));
            String age = String.format("age:(%s)", getParams(ageList));
            String areaName = String.format("area_name:(%s)", getParams(areaNameList));
            String userLevel = String.format("user_level:(%s)", getParams(userLevelList));
            String phoneSystem = String.format("phone_system:(%s)", getParams(phoneSystemList));
            String chnId = String.format("chn_id:(%s)", getParams(chnIdList));

            params = "(" + comType + "AND+" +
                    sex + "AND+" +
                    age + "AND+" +
                    areaName + "AND+" +
                    userLevel + "AND+" +
                    loginStatus + "AND+" +
                    chnId + "AND+" +
                    phoneSystem + ")";
        }

        // 从es查询数据放到redis
        Integer userGroupSizeSum = 0;
        Integer clientUserSum = 0;
        Integer mobileUserSum = 0;
        Integer total = 0;
        Integer size = 10000;

        String result = "";
        String sort = "";
        JSONObject jsonObject;

        Map<String, Integer> retMap = new HashMap<>();
        Map<String, String> infoMap = new HashMap<>();
        infoMap.put("uidStr", "");
        infoMap.put("imeiStr", "");
        infoMap.put("msisdnStr", "");

        // 解析返回结果并存入redis
        String url = String.format("http://%s:%s/%s/_search?sort=row_id:asc&size=%s&q=%s", hosts, port, index, size, params);

        log.debug("===================>>>>>>>>>>>>>>>> url=" + url);
        result = HttpUtil.get(url);
        // log.info("===================>>>>>>>>>>>>>>>> result="+result);
        jsonObject = new JSONObject(result);
        total = Integer.parseInt(jsonObject.getByPath("hits.total").toString());
        Integer page = total / size + 1;

        // 如果大于七百万则不执行
        if (total < 7000000) {
            // 第一次执行获取sort才能进行后续查询
            Map<String, Object> tmpMap = getEsSetAndAddToRedis(groupId, result, redisService);
            userGroupSizeSum += (Integer) tmpMap.get("userGroupSize");
            clientUserSum += (Integer) tmpMap.get("clientUser");
            mobileUserSum += (Integer) tmpMap.get("mobileUser");
            sort = tmpMap.get("sort").toString();

            log.debug("===================>>>>>>>>>>>>>>>> total=" + total);
            log.debug("===================>>>>>>>>>>>>>>>> userGroupSize=" + userGroupSizeSum);
            log.debug("===================>>>>>>>>>>>>>>>> clientUser=" + clientUserSum);
            log.debug("===================>>>>>>>>>>>>>>>> mobileUser=" + mobileUserSum);

            // 如果没取完
            for (int i = 1; i < page; i++) {
                String body = String.format("{\"search_after\":[%s]}", sort);
                log.debug("===================>>>>>>>>>>>>>>>> search_after body=" + body);
                result = HttpUtil.post(url, body);

                tmpMap = getEsSetAndAddToRedis(groupId, result, redisService);
                userGroupSizeSum += (Integer) tmpMap.get("userGroupSize");
                clientUserSum += (Integer) tmpMap.get("clientUser");
                mobileUserSum += (Integer) tmpMap.get("mobileUser");
                sort = tmpMap.get("sort").toString();

                log.debug("===================>>>>>>>>>>>>>>>> total=" + total);
                log.debug("===================>>>>>>>>>>>>>>>> userGroupSize=" + userGroupSizeSum);
                log.debug("===================>>>>>>>>>>>>>>>> clientUser=" + clientUserSum);
                log.debug("===================>>>>>>>>>>>>>>>> mobileUser=" + mobileUserSum);
            }
        }

        // 字符串放到redis
        String uidStr = infoMap.get("uidStr");
        String imeiStr = infoMap.get("imeiStr");
        String msisdnStr = infoMap.get("msisdnStr");
        if (!"".equals(uidStr)) {
            uidStr = uidStr.substring(0, uidStr.length() - 1);
            redisService.set(groupId + "-uid", uidStr);
        }

        if (!"".equals(imeiStr)) {
            imeiStr = imeiStr.substring(0, imeiStr.length() - 1);
            redisService.set(groupId + "-imei", imeiStr);
        }

        if (!"".equals(msisdnStr)) {
            msisdnStr = msisdnStr.substring(0, msisdnStr.length() - 1);
            redisService.set(groupId + "-phone", msisdnStr);
        }

        log.info("===================>>>>>>>>>>>>>>>> total=" + total);
        log.info("===================>>>>>>>>>>>>>>>> userGroupSize=" + userGroupSizeSum);
        log.info("===================>>>>>>>>>>>>>>>> clientUser=" + clientUserSum);
        log.info("===================>>>>>>>>>>>>>>>> mobileUser=" + mobileUserSum);
        retMap.put("total", total);
        retMap.put("userGroupSize", userGroupSizeSum);
        retMap.put("clientUser", clientUserSum);
        retMap.put("mobileUser", mobileUserSum);

        return retMap;
    }

    public static Map<String, Object> getEsSetAndAddToRedis(String groupId, String json, RedisService redisService) {
        Map<String, Object> retMap = new HashMap<>();

        JSONObject jsonObject = new JSONObject(json);
        JSONArray hits = (JSONArray) jsonObject.getByPath("hits.hits");
        Integer total = Integer.parseInt(jsonObject.getByPath("hits.total").toString());
        Integer sort = 0;
        Integer size = hits.size();

        Set<String> clientUserSet = new HashSet<>();
        Set<String> mobileUserSet = new HashSet<>();
        Set msisdnSet = new HashSet<>();
        Set imeiSet = new HashSet<>();
        Set uidSet = new HashSet<>();

        Set set = new TreeSet<>();

        for (int i = 0; i < size; i++) {
            Object obj = hits.get(i);
            String uid = ((JSONObject) obj).getByPath("_source.uid").toString();
            String msisdn = ((JSONObject) obj).getByPath("_source.msisdn").toString();
            String idfa = ((JSONObject) obj).getByPath("_source.idfa").toString();
            String imei = ((JSONObject) obj).getByPath("_source.imei").toString();
            String clentFlag = ((JSONObject) obj).getByPath("_source.client_flag").toString();
            String loginStatus = ((JSONObject) obj).getByPath("_source.login_status").toString();

            if (!"".equals(imei)) {
                set.add(String.format("%s,%s,%s", uid, imei, msisdn));
                imeiSet.add(imei);
            } else {
                set.add(String.format("%s,%s,%s", uid, idfa, msisdn));
                imeiSet.add(idfa);
            }

            msisdnSet.add(msisdn);
            uidSet.add(uid);

            if ("1".equals(clentFlag)) { // 客户端 comType = 1 咪咕用户 2 QQ音乐用户 3 酷我音乐用户 4 酷狗音乐用户 5 网易云音乐用户 6 虾米音乐用户
                clientUserSet.add(uid);
            }
            if ("1".equals(loginStatus)) { // 手机端
                mobileUserSet.add(msisdn);
            }

            if (i == size - 1) {
                sort = (Integer) ((JSONObject) obj).getByPath("_source.row_id");
            }
        }

        fixedThreadPool.submit(() -> {
            // 剔除空数据
            set.remove("");
            msisdnSet.remove("");
            uidSet.remove("");
            imeiSet.remove("");

            // 写入redis
            redisService.setSet(groupId, set);
            redisService.setSet(groupId + "-phone", msisdnSet);
            redisService.setSet(groupId + "-uid", uidSet);
            redisService.setSet(groupId + "-imei", imeiSet);
        });

        retMap.put("userGroupSize", size);
        retMap.put("clientUser", clientUserSet.size());
        retMap.put("mobileUser", mobileUserSet.size());
        retMap.put("total", total);
        retMap.put("sort", sort);

        return retMap;
    }

    public static String getParams(List<String> list) {
        String params = "";

        if (list != null && list.size() > 0) {
            for (String element : list) {
                params += "%22" + element + "%22 ";
            }
        }

        if (!"".equals(params)) {
            params = params.substring(0, params.length() - 1);
        } else {
            params = "%22%22";
        }

        return params;
    }

    public static Map<String, Integer> setFileGroupToRedis(String groupId, String fileName, String fileImporTtype, String onlySms, RedisService redisService, String hosts, String port, String index) throws IOException {
        Map<String, Integer> retMap = new HashMap<>();
        log.info("groupId:{}, fileName:{}, fileImporTtype:{}, onlySms:{}, hosts:{}, port:{}, index:{}", groupId, fileName, fileImporTtype, onlySms, hosts, port, index);
        List<String> allLines = new ArrayList<>();
        try {
            allLines = com.google.common.io.Files.readLines(new File(fileName), Charsets.UTF_8);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        String tmpUrl = String.format("http://%s:%s/%s/_search?q=", hosts, port, index);
        Integer clientUserSum = 0;
        Integer mobileUserSum = 0;
        Integer cnt = 0;
        Set<String> msisdnSet = new HashSet<>();

        // 剃重
        HashSet allLineSet = new HashSet(allLines);
        allLines.clear();
        allLines.addAll(allLineSet);

        if ("1".equals(onlySms)) {
            for (String line : allLines) {
                if (isMsisdn(line)) {
                    msisdnSet.add(line);
                    mobileUserSum++;
                }
            }
            // mobileUserSum = msisdnSet.size();
            if (mobileUserSum > 0) {
                redisService.setSet(groupId + "-phone", msisdnSet);
            }

        } else {

            for (String line : allLines) {
                String url = tmpUrl;
                // 导入文件类型：1-手机号；2-IMEI/IDFA；3-UID；
                if ("1".equals(fileImporTtype)) {
                    // 对手机号码格式进行校验 - 2019-11-26修改
                    if (isMsisdn(line)) {
                        url += "msisdn:" + line;
                    } else {
                        continue;
                    }
                } else if ("2".equals(fileImporTtype) && !line.contains("-")) {
                    url += "imei:" + line;
                } else if ("2".equals(fileImporTtype) && line.contains("-")) {
                    url += "idfa:" + line;
                } else if ("3".equals(fileImporTtype)) {
                    url += "uid:" + line;
                }
                // 执行es 查询
                String result = HttpUtil.get(url);
                // 解析返回结果并存入redis
                Map<String, Object> tmpMap = getEsSetAndAddToRedis(groupId, result, redisService);
                clientUserSum += (Integer) tmpMap.get("clientUser");
                mobileUserSum += (Integer) tmpMap.get("mobileUser");
                Integer total = (Integer) tmpMap.get("total");
                if (total > 0) {
                    cnt++;
                }
            }
        }

        retMap.put("userGroupSize", allLines.size());
        retMap.put("clientUser", clientUserSum);
        retMap.put("mobileUser", mobileUserSum);
        retMap.put("inverCnt", cnt);

        log.info("===================>>>>>>>>>>>>>>>> userGroupSize=" + retMap.get("userGroupSize"));
        log.info("===================>>>>>>>>>>>>>>>> clientUser=" + clientUserSum);
        log.info("===================>>>>>>>>>>>>>>>> mobileUser=" + mobileUserSum);
        return retMap;
    }

    public static Map<String, Integer> setMergeGroupToRedis(String srouceGroupId1, String srouceGroupId2, String targetGroupId, String mergeType, RedisService redisService, String hosts, String port, String index) {
        Map<String, Integer> retMap = new HashMap<>();

        Set result = merge(srouceGroupId1, srouceGroupId2, mergeType, redisService);

        if (result.size() > 7000000) {
            retMap.put("userGroupSize", result.size());
            retMap.put("clientUser", 0);
            retMap.put("mobileUser", 0);

            return retMap;
        }
        redisService.setSet(targetGroupId, result);

        // 存入uid、imei/idfa、msisdn
        Set uidSet = merge(srouceGroupId1 + "-uid", srouceGroupId2 + "-uid", mergeType, redisService);
        Set imeiSet = merge(srouceGroupId1 + "-imei", srouceGroupId2 + "-imei", mergeType, redisService);
        Set msisdnSet = merge(srouceGroupId1 + "-phone", srouceGroupId2 + "-phone", mergeType, redisService);

        redisService.setSet(targetGroupId + "-uid", uidSet);
        redisService.setSet(targetGroupId + "-imei", imeiSet);
        redisService.setSet(targetGroupId + "-phone", msisdnSet);

        retMap.put("userGroupSize", result.size());
        retMap.put("clientUser", imeiSet.size());
        retMap.put("mobileUser", msisdnSet.size());

        return retMap;
    }

    private static Set merge(String srouceGroupId1, String srouceGroupId2, String mergeType, RedisService redisService) {
        Set result = new HashSet();
        Set set1 = redisService.getSet(srouceGroupId1);
        Set set2 = redisService.getSet(srouceGroupId2);
        switch (mergeType) {
            // 4-交集创建
            case "4":
                result.addAll(set1);
                result.retainAll(set2);
                break;
            // 5-并集创建
            case "5":
                result.addAll(set1);
                result.addAll(set2);
                break;
            // 6-左差集创建
            case "6":
                // 先取并集
                result.addAll(set1);
                result.addAll(set2);

                // 差集（左）：两个重组用户群，以第一个用户群为目标用户群，将两个用户群中只要有一个用户标识符（UID、IMEI/IDFA、手机号）相同的用户剔除；
                result.removeAll(set2);
                break;
            // 7-右差集创建
            case "7":
                // 先取并集
                result.addAll(set1);
                result.addAll(set2);

                // 差集（右）：两个重组用户群，以第二个用户群为目标用户群，将两个用户群中只要有一个用户标识符（UID、IMEI/IDFA、手机号）相同的用户剔除；
                result.removeAll(set1);
                break;
            // 8-对称差集创建
            case "8":
                // 先取并集
                result.addAll(set1);
                result.addAll(set2);

                // 取交集
                Set tmpIntersectSet = new HashSet<>();
                tmpIntersectSet.addAll(set1);
                tmpIntersectSet.retainAll(set2);

                // 差集（对称差集）：两个重组用户群，以两个用户群为目标用户群，将两个用户群中只要有一个用户标识符（UID、IMEI/IDFA、手机号）相同的用户剔除；
                result.removeAll(tmpIntersectSet);

                break;
            default:
                break;
        }

        return result;
    }

    /**
     * 对手机号码进行格式校验
     *
     * @param msisdn
     * @return
     */
    private static boolean isMsisdn(String msisdn) {
        //Pattern pattern = Pattern.compile("^(13[0-9]|14[5-9]|15[012356789]|166|17[0-8]|18[0-9]|19[8-9])[0-9]{8}$");
        Pattern pattern = Pattern.compile("^1[0-9]{10}$");
        Matcher matcher = pattern.matcher(msisdn);
        return matcher.matches();
    }
}